﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;

namespace Approve.BLL
{
    /// <summary> 
    /// JSON帮助类 
    /// </summary> 
    public class JsonHelper
    {
        /// <summary> 
        /// 对象转JSON 
        /// </summary> 
        /// <param name="obj">对象</param> 
        /// <returns>JSON格式的字符串</returns> 
        public static string ObjectToJSON(object obj)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            try
            {
                return jss.Serialize(obj);
            }
            catch (Exception ex)
            {
                throw new Exception("JSONHelper.ObjectToJSON(): " + ex.Message);
            }
        }
        /// <summary> 
        /// 数据表转键值对集合 
        /// 把DataTable转成 List集合, 存每一行 
        /// 集合中放的是键值对字典,存每一列 
        /// </summary> 
        /// <param name="dt">数据表</param> 
        /// <returns>哈希表数组</returns> 
        public static List<Dictionary<string, object>> DataTableToList(DataTable dt)
        {
            List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
            foreach (DataRow dr in dt.Rows)
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                foreach (DataColumn dc in dt.Columns)
                {
                    var columnValue = dr.IsNull(dc) ? "" : dr[dc.ColumnName];
                    dic.Add(dc.ColumnName, columnValue);
                }
                list.Add(dic);
            }
            return list;
        }
        /// <summary> 
        /// 数据集转键值对数组字典 
        /// </summary> 
        /// <param name="dataSet">数据集</param> 
        /// <returns>键值对数组字典</returns> 
        public static Dictionary<string, List<Dictionary<string, object>>> DataSetToDic(DataSet ds)
        {
            Dictionary<string, List<Dictionary<string, object>>> result = new Dictionary<string, List<Dictionary<string, object>>>();
            foreach (DataTable dt in ds.Tables)
                result.Add(dt.TableName, DataTableToList(dt));
            return result;
        }
        /// <summary> 
        /// 数据表转JSON 
        /// </summary> 
        /// <param name="dataTable">数据表</param> 
        /// <returns>JSON字符串</returns> 
        public static string DataTableToJSON(DataTable dt)
        {
            return ObjectToJSON(DataTableToList(dt));
        }
        /// <summary> 
        /// JSON文本转对象,泛型方法 
        /// </summary> 
        /// <typeparam name="T">类型</typeparam> 
        /// <param name="jsonText">JSON文本</param> 
        /// <returns>指定类型的对象</returns> 
        public static T JSONToObject<T>(string jsonText)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            try
            {
                return jss.Deserialize<T>(jsonText);
            }
            catch (Exception ex)
            {
                throw new Exception("JSONHelper.JSONToObject(): " + ex.Message);
            }
        }
        /// <summary> 
        /// 将JSON文本转换为数据表数据 
        /// </summary> 
        /// <param name="jsonText">JSON文本</param> 
        /// <returns>数据表字典</returns> 
        public static Dictionary<string, List<Dictionary<string, object>>> TablesDataFromJSON(string jsonText)
        {
            return JSONToObject<Dictionary<string, List<Dictionary<string, object>>>>(jsonText);
        }
        /// <summary> 
        /// 将JSON文本转换成数据行 
        /// </summary> 
        /// <param name="jsonText">JSON文本</param> 
        /// <returns>数据行的字典</returns> 
        public static Dictionary<string, object> DataRowFromJSON(string jsonText)
        {
            return JSONToObject<Dictionary<string, object>>(jsonText);
        }

        /// <summary>
        /// 将json字符串转换成dynamic类型的对象
        /// </summary>
        /// <param name="jsonText"></param>
        /// <returns></returns>
        public static dynamic Deserialize(string jsonText)
        {
            var serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
            return serializer.Deserialize(jsonText, typeof(object));
        }
        /// <summary>
        /// 将dynamic类型的对象转换成json字符串
        /// </summary>
        /// <param name="jsonText"></param>
        /// <returns></returns>
        public static string Serialize(dynamic json)
        {
            var serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new JavaScriptConverter[] { new ExpandoJSONConverter() });
            return serializer.Serialize(json);
        }
        #region class

        private sealed class DynamicJsonConverter : JavaScriptConverter
        {
            public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
            {
                if (dictionary == null)
                    throw new ArgumentNullException("dictionary");

                return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
            }

            public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
            {
                throw new NotImplementedException();
            }

            public override IEnumerable<Type> SupportedTypes
            {
                get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
            }

            #region Nested type: DynamicJsonObject

            private sealed class DynamicJsonObject : DynamicObject
            {
                private readonly IDictionary<string, object> _dictionary;

                public DynamicJsonObject(IDictionary<string, object> dictionary)
                {
                    if (dictionary == null)
                        throw new ArgumentNullException("dictionary");
                    _dictionary = dictionary;
                }

                public override string ToString()
                {
                    var sb = new StringBuilder("{");
                    ToString(sb);
                    return sb.ToString();
                }

                private void ToString(StringBuilder sb)
                {
                    var firstInDictionary = true;
                    foreach (var pair in _dictionary)
                    {
                        if (!firstInDictionary)
                            sb.Append(",");
                        firstInDictionary = false;
                        var value = pair.Value;
                        var name = pair.Key;
                        if (value is string)
                        {
                            sb.AppendFormat("{0}:\"{1}\"", name, value);
                        }
                        else if (value is IDictionary<string, object>)
                        {
                            new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);
                        }
                        else if (value is ArrayList)
                        {
                            sb.Append(name + ":[");
                            var firstInArray = true;
                            foreach (var arrayValue in (ArrayList)value)
                            {
                                if (!firstInArray)
                                    sb.Append(",");
                                firstInArray = false;
                                if (arrayValue is IDictionary<string, object>)
                                    new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);
                                else if (arrayValue is string)
                                    sb.AppendFormat("\"{0}\"", arrayValue);
                                else
                                    sb.AppendFormat("{0}", arrayValue);

                            }
                            sb.Append("]");
                        }
                        else
                        {
                            sb.AppendFormat("{0}:{1}", name, value);
                        }
                    }
                    sb.Append("}");
                }

                public override bool TryGetMember(GetMemberBinder binder, out object result)
                {
                    if (!_dictionary.TryGetValue(binder.Name, out result))
                    {
                        // return null to avoid exception.  caller can check for null this way...
                        result = null;
                        return true;
                    }

                    var dictionary = result as IDictionary<string, object>;
                    if (dictionary != null)
                    {
                        result = new DynamicJsonObject(dictionary);
                        return true;
                    }

                    var arrayList = result as ArrayList;
                    if (arrayList != null && arrayList.Count > 0)
                    {
                        if (arrayList[0] is IDictionary<string, object>)
                            result = new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)));
                        else
                            result = new List<object>(arrayList.Cast<object>());
                    }

                    return true;
                }
            }

            #endregion
        }

        #endregion
    }


    public class ExpandoJSONConverter : JavaScriptConverter
    {
        public override IEnumerable<Type> SupportedTypes
        {
            get
            {
                return new ReadOnlyCollection<Type>(new Type[] { typeof(System.Dynamic.ExpandoObject) });
            }
        }

        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            var result = new Dictionary<string, object>();
            var dictionary = obj as IDictionary<string, object>;
            foreach (var item in dictionary)
            {
                result.Add(item.Key, item.Value);
            }

            return result;
        }
    }
}
